#pragma once

#include <xy/geom/vec.h>

namespace xy
{

namespace geom
{

class camera
{
  protected:
    vec3f m_center;  // 中心位置
    vec3f m_front;   // 指向原点的方向
    vec3f m_up;      // 正交于向前方向的上方
    vec3f m_right;   // 正交于向前方向的右方
    vec3f m_worldUp; // 世界上方项，固定不变 (0, 0, 1)

    // 欧拉角：俯仰角(Pitch)、偏航角(Yaw)和滚转角(Roll)，我们不需要用到滚转角
    float m_distance; // 到原点的距离
    float m_pitch;    // 与 z 轴的夹角
    float m_yaw;      // 与 x 轴的夹角

    // 视锥体参数
    float m_fovy;
    float m_aspect;

    mat4x4f m_viewMat; // 视图矩阵
    mat4x4f m_projMat; // 投影矩阵

  public:
    static constexpr float zNear = 0.1f;
    static constexpr float zFar = 100.0f;

    /**
     * @brief Construct a new camera object
     *
     * @param[in] distance
     * @param[in] pitch
     * @param[in] yaw
     * @param[in] fovy
     * @param[in] aspect
     */
    camera(float distance, float pitch, float yaw, float fovy, float aspect);

    /**
     * @brief 视图矩阵
     *
     * @return mat4x4f
     */
    mat4x4f view() const;

    /**
     * @brief 投影矩阵
     *
     * @return mat4x4f
     */
    mat4x4f projection() const;

    /**
     * @brief 获得俯仰角
     *
     * @return float
     */
    float yaw() const;

    /**
     * @brief 获得偏航角
     *
     * @return float
     */
    float pitch() const;

    /**
     * @brief 获得距离
     *
     * @return float
     */
    float distance() const;

    /**
     * @brief 获得视锥体的垂直视角
     *
     * @return float
     */
    float fovy() const;

    /**
     * @brief 获得视锥体的宽高比
     *
     * @return float
     */
    float aspect() const;

    /**
     * @brief 获得相机前方方向
     *
     * @return vec3f
     */
    vec3f front() const;

    /**
     * @brief 相机位置
     *
     * @return vec3f
     */
    vec3f position() const;

    /**
     * @brief 相机中心
     * 
     * @return vec3f 
     */
    vec3f center() const;

    /**
     * @brief 设置相机中心
     *
     * @param[in] center
     */
    void set_center(const vec3f &center);

    /**
     * @brief 设置俯仰角
     *
     * @param[in] pitch
     */
    void set_pitch(float pitch);

    /**
     * @brief 设置偏航角
     *
     * @param[in] yaw
     */
    void set_yaw(float yaw);

    /**
     * @brief 设置距离
     *
     * @param[in] distance
     */
    void set_distance(float distance);

    /**
     * @brief 设置视锥体的垂直视角
     *
     * @param[in] fovy
     */
    void set_fovy(float fovy);

    /**
     * @brief 设置视锥体的宽高比
     *
     * @param[in] aspect
     */
    void set_aspect(float aspect);

  protected:
    /**
     * @brief 更新相机方向
     *
     */
    void _update_camera_vectors();
};

} // namespace geom

} // namespace xy
